package Listening;

import java.io.File;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.WatchEvent;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;

import org.eclipse.swt.widgets.Event;

import Commnads.ListenCommands;

/**
 *  The Observer executes the commands that had recognized by the {@link Listener},
 *  and updates respectively 
 * @author DROR
 */

public class Observer 
{

	private ListenCommands listencommands;

	/**
	 * Constructor
	 * @param listencommands reference of {@link ListenCommands} class 
	 */
	public Observer(ListenCommands listencommands) 
	{
		this.listencommands = listencommands;
	}

	/**
	 * This function deals with the event that had come from the {@link Listener}
	 * @param event {@link WatchEvent} The type of the {@link Event}
	 * @param child the {@link Path} of the file/folder that had modified/deleted/created
	 */
	public void handle(WatchEvent<?> event,Path child) 
	{
		if (event.kind().name().equals("ENTRY_MODIFY"))
		{
			String p= child.toString();
			File file = new File(child.toString());
			if (file.isDirectory())
			{
				insertToLog("The directory: "+p+"  had modified");
				/* visiting through the directory and tagging the files there */
				Files.walkFileTree(child, new SimpleFileVisitor<Path>() {
					public FileVisitResult visitFile(Path dir, BasicFileAttributes attr) 
					{
						/* checking if we catch a file */
						File file = new File(dir.toString());
						if (file.isFile())
						{
							String f= dir.toString();
							insertToLog("The file: "+getFileNameFromPath(f)+"  had modified");
							listencommands.removeTagsFromFile(f);
							listencommands.autoTag(f);
						}
						return FileVisitResult.CONTINUE;
					}
				});
			}
			else if (file.isFile())
			{
				insertToLog("The file: "+getFileNameFromPath(p)+"  had modified");
				listencommands.removeTagsFromFile(file.toString());
				listencommands.autoTag(file.toString());
			}
		}
		if (event.kind().name().equals("ENTRY_CREATE"))
		{
			String p= child.toString();
			File file = new File(child.toString());
			if (file.isDirectory())
			{
				insertToLog("The directory: "+p+"  had created");
				/* visiting through the directory and tagging the files there */
				Files.walkFileTree(child, new SimpleFileVisitor<Path>() {
					public FileVisitResult visitFile(Path dir, BasicFileAttributes attr) 
					{
						File file = new File(dir.toString());
						/* checking if we catch a file */
						if (file.isFile())
						{
							String f= dir.toString();
							insertToLog("The file: "+getFileNameFromPath(f)+"  had created");
							listencommands.autoTag(f);
						}
						return FileVisitResult.CONTINUE;
					}
				});
			}
			else if (file.isFile())
			{
				insertToLog("The file: "+getFileNameFromPath(p)+"  had created");
				listencommands.autoTag(file.toString());
			}

		}
		if (event.kind().name().equals("ENTRY_DELETE"))
		{
			String p= child.toString();
			if (checkPathOrFile(p))
				insertToLog("The file: "+getFileNameFromPath(p)+"  had deleted");
			else
				insertToLog("The directory: "+p+"  had deleted");
			listencommands.removeDir(child.toString());
		}
	}


	/**
	 * This function returns all listened directories from DB
	 * @return an {@link ArrayList} of all listened directories from DB
	 */
	public ArrayList<String> getDirectories()
	{
		return listencommands.getDirectories();
	}

	/**
	 * This function extracts file's name from his path
	 * @param path The path of file by {@link String}
	 * @return The name of file by {@link String}
	 */
	public String getFileNameFromPath(String path)
	{
		String words[]=path.split("\\\\");
		int len= words.length;
		return words[len-1];
	}
	/**
	 * This function checking if we going to delete file or directory
	 * @param path The path directory/file by {@link String}
	 * @return {@link Boolean} true if it's a file
	 */
	public boolean checkPathOrFile(String path)
	{
		String words[]=path.split("\\\\");
		int len= words.length;
		String last[]=words[len-1].split("\\.");
		if (last.length==1)
			return false;
		return true;
	}
	/**
	 * This function updates the Log about new operation
	 * @param oper The operation by {@link String} that had been recognized
	 */
	public void insertToLog(String oper)
	{
		listencommands.insertToLog(oper);
	}
}
